﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Configuration;
using CristoRessuscitado.Utils;
using CristoRessuscitado.BancoDados;
using System.Data.SqlClient;

namespace CristoRessuscitado.Formularios
{
    public partial class FormConfigBancoDados : Form, IFormCadPadrao
    {

        private FormCarregando formCarregandoDialog;
        
        private bool           conexaoValida;


        public FormConfigBancoDados()
        {
            InitializeComponent();
        }

        // ---------------------------------------------------------------------------------------------------------------------------
        //
        // Eventos
        //
        // ---------------------------------------------------------------------------------------------------------------------------

        private void FormConfigBancoDados_Load(object sender, EventArgs e)
        {
            Inicializar();
        }

        private void FormConfigBancoDados_KeyDown(object sender, KeyEventArgs e)
        {
            OnTecladoKeyDown(e);
        }

        private void btnSalvar_Click(object sender, EventArgs e)
        {
            if (Validar())
            {
                Salvar();
                GeralUtils.ExibirDialogMsgInfo(this, 
                    "As configurações da conexão com o banco de dados foram alteradas e por isso o sistema será reiniciado automaticamente.");
                GeralUtils.ReiniciarAplicacao();
            }
        }

        // ---------------------------------------------------------------------------------------------------------------------------
        //
        // Métodos Auxiliares
        //
        // ---------------------------------------------------------------------------------------------------------------------------

        public void OnTecladoKeyDown(KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Escape)
            {
                Close();
            }
        }

        public void Inicializar()
        {
            KeyPreview = true;
            PopularCamposParaAlteracao();
        }

        public void PopularCamposParaInclusao()
        { }

        
        public void PopularCamposParaAlteracao()
        {
            var cnSection = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
            String connString = cnSection.ConnectionStrings.ConnectionStrings[StringConexaoEFIdentificadores.CONNECTION_NAME].ConnectionString;

            string servidor = BuscarConnStringItemValue(connString, StringConexaoEFIdentificadores.PROVIDER_CONNECTION_DATA_SOURCE);
            string nomeBanco = BuscarConnStringItemValue(connString, StringConexaoEFIdentificadores.INITIAL_CATALOG);
            string usuario = BuscarConnStringItemValue(connString, StringConexaoEFIdentificadores.USER_ID);
            string senha = BuscarConnStringItemValue(connString, StringConexaoEFIdentificadores.PASSWORD);

            tbServidor.Text = servidor;
            tbNomeBanco.Text = nomeBanco;
            tbUsuario.Text = usuario;
            tbSenha.Text = senha;
        }

        public bool Validar()
        {
            string servidor = tbServidor.Text.Trim();
            if (string.IsNullOrEmpty(servidor))
            {
                GeralUtils.ExibirDialogMsgValidacao(this, "Informe o servidor.");
                tbServidor.Focus();
                return false;
            }

            string banco = tbNomeBanco.Text.Trim();
            if (string.IsNullOrEmpty(banco))
            {
                GeralUtils.ExibirDialogMsgValidacao(this, "Informe o nome do banco.");
                tbNomeBanco.Focus();
                return false;
            }

            string usuario = tbUsuario.Text.Trim();
            if (string.IsNullOrEmpty(usuario))
            {
                GeralUtils.ExibirDialogMsgValidacao(this, "Informe o nome do usuário.");
                tbUsuario.Focus();
                return false;
            }

            string senha = tbSenha.Text.Trim();
            if (string.IsNullOrEmpty(senha))
            {
                GeralUtils.ExibirDialogMsgValidacao(this, "Informe a senha.");
                tbSenha.Focus();
                return false;
            }

            // Thread
            BackgroundWorker bw = new BackgroundWorker();
            bw.DoWork += new DoWorkEventHandler(bw_DoWork);
            bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);

            formCarregandoDialog = new FormCarregando();
            
            bw.RunWorkerAsync();
            formCarregandoDialog.ShowDialog(this);

            if (!conexaoValida)
            {
                GeralUtils.ExibirDialogMsgValidacao(this, "Não foi possível conectar ao servidor de banco de dados. Verifique os dados informados.");
                return false;
            }

            return true;
        }

        public void bw_DoWork(object sender, DoWorkEventArgs e)
        {
            string servidor = tbServidor.Text.Trim();
            string banco = tbNomeBanco.Text.Trim();
            string usuario = tbUsuario.Text.Trim();
            string senha = tbSenha.Text.Trim();

            conexaoValida = GeralUtils.ValidarConexaoSQL(servidor, banco, usuario, senha);
        }

        public void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            formCarregandoDialog.Close();
        }

        public void Salvar()
        {
            string servidor = tbServidor.Text.Trim();
            string banco = tbNomeBanco.Text.Trim();
            string usuario = tbUsuario.Text.Trim();
            string senha = tbSenha.Text.Trim();

            AlterarConexaoNoAppConfig(servidor, banco, usuario, senha);
        }

        private void AlterarConexaoNoAppConfig(string servidor, string banco, string usuario, string senha)
        {
            var cnSection = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
            String connString = cnSection.ConnectionStrings.ConnectionStrings[StringConexaoEFIdentificadores.CONNECTION_NAME].ConnectionString;
            connString = MudarConnStringItem(connString, StringConexaoEFIdentificadores.PROVIDER_CONNECTION_DATA_SOURCE, servidor);
            connString = MudarConnStringItem(connString, StringConexaoEFIdentificadores.INITIAL_CATALOG, banco);
            connString = MudarConnStringItem(connString, StringConexaoEFIdentificadores.USER_ID, usuario);
            connString = MudarConnStringItem(connString, StringConexaoEFIdentificadores.PASSWORD, senha);
            cnSection.ConnectionStrings.ConnectionStrings[StringConexaoEFIdentificadores.CONNECTION_NAME].ConnectionString = connString;
            cnSection.Save();
            ConfigurationManager.RefreshSection(StringConexaoEFIdentificadores.CONNECTION_SECTION);
        }

        public static String BuscarConnStringItemValue(string connString, string option)
        {
            String[] conItens = connString.Split(';');
            String resultado = "";
            foreach (String item in conItens)
            {
                string itemTrim = item.Trim();
                if (itemTrim.StartsWith(option))
                {
                    String[] optionValue = item.Split('=');

                    if (itemTrim.StartsWith(StringConexaoEFIdentificadores.PROVIDER_CONNECTION_DATA_SOURCE))
                        resultado = optionValue[2];
                    else
                        resultado = optionValue[1];
                }
            }
            return resultado;
        }

        private String MudarConnStringItem(string connString, string option, string value)
        {
            String[] conItens = connString.Split(';');
            String resultado = "";
            foreach (String item in conItens)
            {
                string itemTrim = item.Trim();
                if (itemTrim.StartsWith(option))
                {
                    resultado += option + "=" + value + ";";
                }
                else
                {
                    resultado += item + ";";
                }
            }
            return resultado;
        }

        /**
         * Representa as constantes identificadoras da String de Conexão do Entity Framework 
         */
        public class StringConexaoEFIdentificadores
        {
            public const string CONNECTION_SECTION              = "DatabaseContext";
            public const string CONNECTION_NAME                 = "DatabaseContext";
            public const string PROVIDER_CONNECTION_DATA_SOURCE = "provider connection string=\"data source";
            public const string INITIAL_CATALOG                 = "initial catalog";
            public const string USER_ID                         = "user id";
            public const string PASSWORD                        = "password";
        }
    }
}
